package com.bluepixel.tvitalia;

import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import com.bugsense.trace.BugSenseHandler;
import com.google.ads.AdRequest;
import com.google.ads.AdView;

public class VideoListActivity extends Activity {

    private ProgressDialog progDailog;
    VideoListAdapter adapter;
    ArrayList<HashMap<String, Object>> data=new ArrayList<HashMap<String, Object>>();
    private final List<String> arrayVideoId=new ArrayList<String>();
    private boolean dataAvailable=false;
    private int totalEntries=50;
    //
    private final String YT_API_URL_PT1="http://gdata.youtube.com/feeds/api/playlists/";
    private final String YT_API_URL_PT2="max-results=50&orderby=published&v=2";
    private final String YT_URL_PREFIX="http://www.youtube.com/watch?v=";
    static final String PLAYLIST_TOTAL_ENTRIES="openSearch:totalResults";
    static final String ENTRY_TITLE="title";
    static final String ENTRY_DESCR="media:description";
    static final String ENTRY_VIDEOID="yt:videoid";
    static final String ENTRY_THUMB="media:thumbnail";
    static final String ENTRY_GROUP="media:group";
    static final String ENTRY_DATE="published";
    static final String TAG_URL="url";
    //
    public static final int[] LOADING_MSGS=new int[]{R.string.loading01, R.string.loading02, R.string.loading03,
	R.string.loading04, R.string.loading05 };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_video_list);
	new DataConnection().execute();
    }

    private void readXml() {
	if (dataAvailable) {
	    AdView adView=(AdView) this.findViewById(R.id.adViewVideo);
	    adView.loadAd(new AdRequest());
	    progDailog=ProgressDialog.show(this, getText(R.string.loading_title), getText(R.string.loading));
	    new Connection().execute();
	}
	else {
	    ListView lv=(ListView) findViewById(R.id.videoListView);
	    lv.setVisibility(View.GONE);
	    TextView tv=(TextView) findViewById(R.id.emptyTextVideo);
	    tv.setVisibility(View.VISIBLE);
	}
    }

    private int getTotalEntries() throws ParserConfigurationException, SAXException, IOException {
	// Get playlist ID
	Bundle extras=getIntent().getExtras();
	String apiUrl=YT_API_URL_PT1 + extras.getString(Utils.PLAYLIST_TAG) + "?v=2";
	//
	SimpleDateFormat formatter=new SimpleDateFormat("dd/mm/yyyy");
	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-mm-dd");
	//
	final XMLParser parser=new XMLParser();
	URL url=new URL(apiUrl);
	DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
	DocumentBuilder db=dbf.newDocumentBuilder();
	Document doc=db.parse(new InputSource(url.openStream()));
	doc.getDocumentElement().normalize();
	Element e=(Element) doc.getFirstChild();
	return Integer.parseInt((parser.getValue(e, PLAYLIST_TOTAL_ENTRIES)));
    }

    private void apiCall() throws ParserConfigurationException, SAXException, IOException {
	// Get playlist ID
	Bundle extras=getIntent().getExtras();
	// String apiUrl=YT_API_URL_PT1 + extras.getString(Utils.PLAYLIST_TAG) + "?start-index=" +
	// (totalEntries - 49)
	// + "&" + YT_API_URL_PT2;
	// if ((totalEntries <= 49) || (totalEntries >= 999)) {
	String apiUrl=YT_API_URL_PT1 + extras.getString(Utils.PLAYLIST_TAG) + "?" + YT_API_URL_PT2;
	// }

	//
	SimpleDateFormat formatter=new SimpleDateFormat("dd/mm/yyyy");
	SimpleDateFormat sdf=new SimpleDateFormat("yyyy-mm-dd");
	//
	final XMLParser parser=new XMLParser();
	URL url=new URL(apiUrl);
	DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
	DocumentBuilder db=dbf.newDocumentBuilder();
	Document doc=db.parse(new InputSource(url.openStream()));
	doc.getDocumentElement().normalize();
	NodeList nl=doc.getElementsByTagName("entry");
	//
	for (int i=0; i < nl.getLength(); ++i) {
	    Element e=(Element) nl.item(i);
	    NodeList nlGroup=e.getElementsByTagName(ENTRY_GROUP);
	    Drawable drawable=null;
	    Element ee=(Element) nlGroup.item(0);
	    NodeList nlThumbs=(ee.getElementsByTagName(ENTRY_THUMB));
	    Element eee=(Element) nlThumbs.item(0);
	    URL thumb_u=new URL(eee.getAttribute(TAG_URL));
	    drawable=Drawable.createFromStream(thumb_u.openStream(), "src");

	    // Retriving published date
	    String dateValue=(parser.getValue(e, ENTRY_DATE)).substring(0, 10);
	    Date xmlDate=null;
	    try {
		xmlDate=sdf.parse(dateValue);
	    }
	    catch (Exception ex) {
		BugSenseHandler.addCrashExtraData("marker", "apiCall > xmlDate=sdf.parse(dateValue);");
		BugSenseHandler.sendException(ex);
	    }
	    String formattedDate=formatter.format(xmlDate);

	    HashMap<String, Object> map=new HashMap<String, Object>();
	    map.put(ENTRY_TITLE, parser.getValue(e, ENTRY_TITLE));
	    map.put(ENTRY_DESCR, parser.getValue(e, ENTRY_DESCR));
	    map.put(ENTRY_DATE, formattedDate);
	    map.put(ENTRY_THUMB, drawable);
	    data.add(map);
	    arrayVideoId.add(parser.getValue(e, ENTRY_VIDEOID));
	}
    }

    private void buildList() {
	ListView lv=(ListView) findViewById(R.id.videoListView);
	adapter=new VideoListAdapter(this, data);
	lv.setAdapter(adapter);
	// listening to single listitem click
	lv.setOnItemClickListener(new OnItemClickListener() {
	    @Override
	    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		String youtubeUrl=YT_URL_PREFIX + arrayVideoId.get(position);
		Intent browserIntent=new Intent(Intent.ACTION_VIEW, Uri.parse(youtubeUrl));
		startActivity(browserIntent);
	    }
	});
    }

    private boolean isNetworkAvailable() {
	ConnectivityManager connectivityManager=(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
	NetworkInfo activeNetworkInfo=connectivityManager.getActiveNetworkInfo();
	return (activeNetworkInfo != null) && activeNetworkInfo.isConnected();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
	switch (item.getItemId()) {
	    case R.id.action_contatti:
		Intent email=new Intent(Intent.ACTION_SEND);
		email.putExtra(Intent.EXTRA_EMAIL, new String[]{getResources().getString(R.string.mail_to) });
		email.putExtra(Intent.EXTRA_SUBJECT, getResources().getString(R.string.mail_subj));
		email.setType("message/rfc822");
		startActivity(Intent.createChooser(email, getResources().getString(R.string.action_contatti)));
		break;
	    case R.id.action_friend:
		Intent emailFriend=new Intent(Intent.ACTION_SEND);
		emailFriend.putExtra(Intent.EXTRA_SUBJECT, getResources().getString(R.string.mail_friend_subj));
		emailFriend.putExtra(Intent.EXTRA_TEXT, getResources().getString(R.string.mail_friend_text));
		emailFriend.setType("message/rfc822");
		startActivity(Intent.createChooser(emailFriend, getResources().getString(R.string.action_friend)));
		break;
	    case R.id.action_info:
		new AlertDialog.Builder(this)
		    .setTitle(getResources().getString(R.string.action_info))
		    .setMessage(getResources().getString(R.string.action_info_text))
		    .setPositiveButton(getResources().getString(R.string.btn_ok),
			new DialogInterface.OnClickListener() {
			    @Override
			    public void onClick(DialogInterface dialog, int which) {
				dialog.cancel();
			    }
			}).show();
		break;
	    case R.id.action_vote:
		Intent i=new Intent(Intent.ACTION_VIEW, Uri.parse(getResources().getString(R.string.action_vote_url)));
		startActivity(i);
		break;

	    default:
		break;
	}

	return true;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
	// Inflate the menu; this adds items to the action bar if it is present.
	getMenuInflater().inflate(R.menu.video_list, menu);
	return true;
    }

    private class Connection extends AsyncTask {

	@Override
	protected Object doInBackground(Object... arg0) {
	    Timer timer=new Timer("update");
	    timer.scheduleAtFixedRate(new TimerTask() {
		@Override
		public void run() {
		    runOnUiThread(new Runnable() {
			@Override
			public void run() {
			    runOnUiThread(changeMessage);
			}
		    });
		}
	    }, 0, Utils.LOADING_MSG_MILLS);

	    try {
		totalEntries=getTotalEntries();
		apiCall();
	    }
	    catch (Exception e) {
		BugSenseHandler.addCrashExtraData("marker", "Connection > doInBackground > apiCall");
		BugSenseHandler.sendException(e);
	    }
	    return null;
	}

	@Override
	protected void onPreExecute() {
	    progDailog.setIndeterminate(true);
	}

	@Override
	protected void onPostExecute(Object result) {
	    super.onPostExecute(result);
	    progDailog.dismiss();
	    buildList();
	}

	@Override
	protected void onCancelled() {
	    progDailog.dismiss();
	    super.onCancelled();
	}
    }

    private class DataConnection extends AsyncTask {
	@Override
	protected Object doInBackground(Object... arg0) {
	    dataAvailable=isNetworkAvailable();
	    return null;
	}

	@Override
	protected void onPostExecute(Object result) {
	    super.onPostExecute(result);
	    try {
		readXml();
	    }
	    catch (Exception e) {
		readXml();
		progDailog.dismiss();
		BugSenseHandler.addCrashExtraData("marker", "DataConnection > onPostExecute > readXml");
		BugSenseHandler.sendException(e);
	    }
	}
    }

    private final Runnable changeMessage=new Runnable() {
	@Override
	public void run() {
	    Random r=new Random();
	    progDailog.setMessage(getResources().getString(LOADING_MSGS[r.nextInt(5)]));
	}
    };
}
